#pragma once
#ifndef __ROUTERCLIENT_H__
#define __ROUTERCLIENT_H__

#include <app/App.h>
#include <string_view>
#include <memory>
#include <msg/message.h>
#include <net/tcp_client.hpp>
#include <router/RouterControlServer.h>
#include <thread>
#include <unordered_map>
#include <util/DataQueue.hpp>
#include <util/Epoll.hpp>
#include <util/singleton.hpp>
#include <util/thread_pool.hpp>


class RouterClient
{
public:
    RouterClient(uint16_t ctl_port);

    std::shared_ptr<App> get_app(uint32_t id);

    uint32_t get_app_id(std::shared_ptr<App> app);

    std::shared_ptr<RouterControlServer> get_controller();

    uint32_t register_app(std::shared_ptr<App> app);

    void unregister_app(std::shared_ptr<App> app);

    uint32_t get_user_id();

    uint32_t get_host_id();

    void start(std::string_view server_ip, uint16_t server_port);

    void wait();

    void read_thread_func();

    void write_thread_func();

    void put_message(message msg);

    // RouterClient* router   后面考虑下如何去掉这个
    static void read_from_fd(RouterClient* router, epoll_data_t data);

private:
    void set_user_host(uint32_t user, uint32_t host);

    void set_controller(uint32_t ctl_port);

private:
    // 可以整合成一个app_table
    std::unordered_map<uint32_t, std::shared_ptr<App>> app_table;
    std::unordered_map<std::shared_ptr<App>, uint32_t> id_table;

    Epoll ep;
    tcp_client client;
    DataQueue<message> message_send_queue;
    uint32_t user_id, host_id;
    uint32_t app_id;
    ThreadPool thread_pool;

    std::thread read_thread;
    std::thread write_thread;
    friend class RouterControlServer;

public:
    enum {
        ROUTERCLIENT_ID = 0,
        CONTROLLER_ID = 1
    };
};

#define RouterClient_init(ctl_port) \
template<>  \
inline RouterClient EagerSingleton<RouterClient>::instance = RouterClient(ctl_port);

#define router_client  EagerSingleton<RouterClient>::getInstance()
 
#define routerctl (*(router_client.get_controller()))
 #endif // __ROUTERCLIENT_H__